В этом документе объясняется, как приложения веб-сервера используют клиентские библиотеки Google API или конечные точки Google OAuth 2.0 для реализации авторизации OAuth 2.0 для доступа к API данных YouTube.
OAuth 2.0 позволяет пользователям делиться определенными данными с приложением, сохраняя при этом свои имена пользователей, пароли и другую информацию конфиденциальной. Например, приложение может использовать OAuth 2.0 для получения разрешения на загрузку видео на канал пользователя YouTube.
Этот поток OAuth 2.0 предназначен специально для авторизации пользователя. Он разработан для приложений, которые могут хранить конфиденциальную информацию и поддерживать состояние. Правильно авторизованное приложение веб-сервера может получить доступ к API, пока пользователь взаимодействует с приложением или после того, как пользователь покинул приложение.
Приложения веб-сервера часто также используют учетные записи служб для авторизации запросов API, особенно при вызове API Cloud для доступа к данным на основе проекта, а не к данным, специфичным для пользователя. Приложения веб-сервера могут использовать учетные записи служб в сочетании с авторизацией пользователя. Обратите внимание, что API данных YouTube поддерживает поток учетных записей служб только для владельцев контента YouTube, которые владеют и управляют несколькими каналами YouTube. В частности, владельцы контента могут использовать учетные записи служб для вызова методов API, которые поддерживают параметр запроса onBehalfOfContentOwner
.
Клиентские библиотеки
Примеры, специфичные для языка, на этой странице используют клиентские библиотеки Google API для реализации авторизации OAuth 2.0. Для запуска примеров кода необходимо сначала установить клиентскую библиотеку для вашего языка.
Когда вы используете клиентскую библиотеку Google API для обработки потока OAuth 2.0 вашего приложения, клиентская библиотека выполняет множество действий, которые в противном случае приложению пришлось бы выполнять самостоятельно. Например, она определяет, когда приложение может использовать или обновлять сохраненные токены доступа, а также когда приложение должно повторно получить согласие. Клиентская библиотека также генерирует правильные URL-адреса перенаправления и помогает реализовать обработчики перенаправления, которые обмениваются кодами авторизации на токены доступа.
Клиентские библиотеки Google API для серверных приложений доступны для следующих языков:
Предпосылки
Включите API для вашего проекта
Любое приложение, которое вызывает API Google, должно включить эти API в API Console.
Чтобы включить API для вашего проекта:
- Open the API Library в Google API Console.
- If prompted, select a project, or create a new one.
- Используйте страницу библиотеки , чтобы найти и включить API данных YouTube. Найдите любые другие API, которые будет использовать ваше приложение, и включите их тоже.
Создать учетные данные для авторизации
Любое приложение, использующее OAuth 2.0 для доступа к API Google, должно иметь учетные данные авторизации, которые идентифицируют приложение на сервере OAuth 2.0 Google. Следующие шаги объясняют, как создать учетные данные для вашего проекта. Затем ваши приложения могут использовать учетные данные для доступа к API, которые вы включили для этого проекта.
- Go to the Credentials page.
- Нажмите «Создать клиента» .
- Выберите тип приложения Веб-приложение .
- Заполните форму и нажмите «Создать» . Приложения, использующие такие языки и фреймворки, как PHP, Java, Python, Ruby и .NET, должны указывать авторизованные URI перенаправления . URI перенаправления — это конечные точки, на которые сервер OAuth 2.0 может отправлять ответы. Эти конечные точки должны соответствовать правилам проверки Google .
Для тестирования вы можете указать URI, которые ссылаются на локальную машину, например
http://localhost:8080
. Имея это в виду, обратите внимание, что все примеры в этом документе используютhttp://localhost:8080
в качестве URI перенаправления.Мы рекомендуем вам разработать конечные точки аутентификации вашего приложения таким образом, чтобы ваше приложение не предоставляло коды авторизации другим ресурсам на странице.
После создания учетных данных загрузите файл client_secret.json с сайта API Console. Надежно сохраните файл в месте, к которому будет иметь доступ только ваше приложение.
Определить области доступа
Области действия позволяют вашему приложению запрашивать доступ только к тем ресурсам, которые ему нужны, а также позволяют пользователям контролировать объем доступа, который они предоставляют вашему приложению. Таким образом, может существовать обратная зависимость между количеством запрошенных областей действия и вероятностью получения согласия пользователя.
Прежде чем приступить к реализации авторизации OAuth 2.0, мы рекомендуем вам определить области, для доступа к которым вашему приложению потребуется разрешение.
Мы также рекомендуем, чтобы ваше приложение запрашивало доступ к областям авторизации через процесс инкрементальной авторизации , в котором ваше приложение запрашивает доступ к пользовательским данным в контексте. Эта передовая практика помогает пользователям легче понять, почему вашему приложению нужен запрашиваемый им доступ.
API данных YouTube v3 использует следующие области действия:
Сферы | |
---|---|
https://www.googleapis.com/auth/youtube | Управляйте своим аккаунтом YouTube |
https://www.googleapis.com/auth/youtube.channel-memberships.creator | Просматривайте список ваших текущих активных участников канала, их текущий уровень и время, когда они стали участником. |
https://www.googleapis.com/auth/youtube.force-ssl | Просматривайте, редактируйте и безвозвратно удаляйте свои видео, рейтинги, комментарии и подписи на YouTube. |
https://www.googleapis.com/auth/youtube.readonly | Просмотрите свой аккаунт YouTube |
https://www.googleapis.com/auth/youtube.upload | Управляйте своими видео на YouTube |
https://www.googleapis.com/auth/youtubepartner | Просмотр и управление своими объектами и связанным контентом на YouTube |
https://www.googleapis.com/auth/youtubepartner-channel-audit | Просмотр личной информации о вашем канале YouTube, актуальной в процессе аудита с партнером YouTube. |
Документ «Области действия API OAuth 2.0» содержит полный список областей действия, которые можно использовать для доступа к API Google.
Требования к конкретному языку
Для запуска любого из примеров кода в этом документе вам понадобится учетная запись Google, доступ к Интернету и веб-браузер. Если вы используете одну из клиентских библиотек API, также ознакомьтесь с требованиями к языку ниже.
PHP
Для запуска примеров PHP-кода из этого документа вам понадобится:
- PHP 8.0 или выше с установленным интерфейсом командной строки (CLI) и расширением JSON.
- Инструмент управления зависимостями Composer .
Клиентская библиотека Google API для PHP:
composer require google/apiclient:^2.15.0
Более подробную информацию см. в Клиентской библиотеке API Google для PHP .
Питон
Для запуска примеров кода Python, приведенных в этом документе, вам понадобится:
- Python 3.7 или выше
- Инструмент управления пакетами pip .
- Выпуск клиентской библиотеки API Google для Python 2.0:
pip install --upgrade google-api-python-client
google-auth
,google-auth-oauthlib
иgoogle-auth-httplib2
для авторизации пользователей.pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
- Фреймворк веб-приложений Flask Python.
pip install --upgrade flask
- Библиотека HTTP-
requests
.pip install --upgrade requests
Если вы не можете обновить Python, ознакомьтесь с примечанием к выпуску клиентской библиотеки Google API Python и соответствующим руководством по миграции.
Рубин
Для запуска примеров кода Ruby, представленных в этом документе, вам понадобится:
- Ruby 2.6 или выше
Библиотека аутентификации Google для Ruby:
gem install googleauth
Фреймворк веб-приложений Sinatra Ruby.
gem install sinatra
Node.js
Для запуска примеров кода Node.js из этого документа вам понадобится:
- Поддерживаемая LTS, активная LTS или текущая версия Node.js.
Клиент Node.js API Google:
npm install googleapis crypto express express-session
HTTP/REST
Вам не нужно устанавливать какие-либо библиотеки, чтобы иметь возможность напрямую вызывать конечные точки OAuth 2.0.
Получение токенов доступа OAuth 2.0
Следующие шаги показывают, как ваше приложение взаимодействует с сервером OAuth 2.0 Google для получения согласия пользователя на выполнение запроса API от имени пользователя. Ваше приложение должно иметь это согласие, прежде чем оно сможет выполнить запрос API Google, требующий авторизации пользователя.
Список ниже кратко суммирует эти шаги:
- Ваше приложение определяет необходимые ему разрешения.
- Ваше приложение перенаправляет пользователя в Google вместе со списком запрошенных разрешений.
- Пользователь сам решает, предоставлять ли разрешения вашему приложению.
- Ваше приложение узнает, какое решение принял пользователь.
- Если пользователь предоставил запрошенные разрешения, ваше приложение извлекает токены, необходимые для выполнения запросов API от имени пользователя.
Шаг 1: Установите параметры авторизации
Ваш первый шаг — создать запрос на авторизацию. Этот запрос устанавливает параметры, которые идентифицируют ваше приложение и определяют разрешения, которые пользователю будет предложено предоставить вашему приложению.
- Если вы используете клиентскую библиотеку Google для аутентификации и авторизации OAuth 2.0, вы создаете и настраиваете объект, который определяет эти параметры.
- Если вы напрямую вызовете конечную точку Google OAuth 2.0, вы сгенерируете URL-адрес и зададите параметры для этого URL-адреса.
Вкладки ниже определяют поддерживаемые параметры авторизации для приложений веб-сервера. Примеры, специфичные для языка, также показывают, как использовать клиентскую библиотеку или библиотеку авторизации для настройки объекта, который задает эти параметры.
PHP
Следующий фрагмент кода создает объект Google\Client()
, который определяет параметры в запросе авторизации.
Этот объект использует информацию из вашего файла client_secret.json для идентификации вашего приложения. (См. создание учетных данных авторизации для получения дополнительной информации об этом файле.) Объект также определяет области, к которым ваше приложение запрашивает разрешение на доступ, и URL-адрес конечной точки аутентификации вашего приложения, которая будет обрабатывать ответ от сервера Google OAuth 2.0. Наконец, код задает необязательные параметры access_type
и include_granted_scopes
.
Например, этот код запрашивает автономный доступ для управления аккаунтом пользователя YouTube:
use Google\Client; $client = new Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfig('client_secret.json'); // Required, to set the scope value, call the addScope function $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); // Required, call the setRedirectUri function to specify a valid redirect URI for the // provided client_id $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType('offline'); // Recommended, call the setState function. Using a state value can increase your assurance that // an incoming connection is the result of an authentication request. $client->setState($sample_passthrough_value); // Optional, if your application knows which user is trying to authenticate, it can use this // parameter to provide a hint to the Google Authentication Server. $client->setLoginHint('hint@example.com'); // Optional, call the setPrompt function to set "consent" will prompt the user for consent $client->setPrompt('consent'); // Optional, call the setIncludeGrantedScopes function with true to enable incremental // authorization $client->setIncludeGrantedScopes(true);
Питон
Следующий фрагмент кода использует модуль google-auth-oauthlib.flow
для построения запроса на авторизацию.
Код создает объект Flow
, который идентифицирует ваше приложение, используя информацию из файла client_secret.json , который вы загрузили после создания учетных данных авторизации . Этот объект также идентифицирует области, к которым ваше приложение запрашивает разрешение на доступ, и URL-адрес конечной точки аутентификации вашего приложения, которая будет обрабатывать ответ от сервера Google OAuth 2.0. Наконец, код задает необязательные параметры access_type
и include_granted_scopes
.
Например, этот код запрашивает автономный доступ для управления аккаунтом пользователя YouTube:
import google.oauth2.credentials import google_auth_oauthlib.flow # Required, call the from_client_secrets_file method to retrieve the client ID from a # client_secret.json file. The client ID (from that file) and access scopes are required. (You can # also use the from_client_config method, which passes the client configuration as it originally # appeared in a client secrets file but doesn't access the file itself.) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file('client_secret.json', scopes=['https://www.googleapis.com/auth/youtube.force-ssl']) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = 'https://www.example.com/oauth2callback' # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. authorization_url, state = flow.authorization_url( # Recommended, enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Optional, enable incremental authorization. Recommended as a best practice. include_granted_scopes='true', # Optional, if your application knows which user is trying to authenticate, it can use this # parameter to provide a hint to the Google Authentication Server. login_hint='hint@example.com', # Optional, set prompt to 'consent' will prompt the user for consent prompt='consent')
Рубин
Используйте файл client_secrets.json, который вы создали, чтобы настроить клиентский объект в вашем приложении. При настройке клиентского объекта вы указываете области, к которым вашему приложению необходимо получить доступ, а также URL-адрес конечной точки аутентификации вашего приложения, которая будет обрабатывать ответ от сервера OAuth 2.0.
Например, этот код запрашивает автономный доступ для управления аккаунтом пользователя YouTube:
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/youtube_v3' # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value scope = 'https://www.googleapis.com/auth/youtube.force-ssl' # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. callback_uri = '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, callback_uri)
Ваше приложение использует клиентский объект для выполнения операций OAuth 2.0, таких как генерация URL-адресов запросов авторизации и применение токенов доступа к HTTP-запросам.
Node.js
Следующий фрагмент кода создает объект google.auth.OAuth2
, который определяет параметры в запросе авторизации.
Этот объект использует информацию из вашего файла client_secret.json для идентификации вашего приложения. Чтобы запросить у пользователя разрешения на получение токена доступа, вы перенаправляете его на страницу согласия. Чтобы создать URL-адрес страницы согласия:
const {google} = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI * from the client_secret.json file. To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for YouTube API const scopes = [ 'https://www.googleapis.com/auth/youtube.force-ssl' ]; // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity and Google Calendar scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state });
Важное примечание - refresh_token
возвращается только при первой авторизации. Подробнее здесь .
HTTP/REST
Конечная точка OAuth 2.0 от Google находится по адресу https://accounts.google.com/o/oauth2/v2/auth
. Эта конечная точка доступна только через HTTPS. Обычные HTTP-подключения отклоняются.
Сервер авторизации Google поддерживает следующие параметры строки запроса для приложений веб-сервера:
Параметры | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
client_id | Необходимый Идентификатор клиента для вашего приложения. Вы можете найти это значение в . | ||||||||||||||||
redirect_uri | Необходимый Определяет, куда сервер API перенаправляет пользователя после того, как пользователь завершает поток авторизации. Значение должно точно соответствовать одному из авторизованных URI перенаправления для клиента OAuth 2.0, который вы настроили в клиенте . Если это значение не соответствует авторизованному URI перенаправления для предоставленного Обратите внимание, что схема | ||||||||||||||||
response_type | Необходимый Определяет, возвращает ли конечная точка Google OAuth 2.0 код авторизации. Установите значение параметра | ||||||||||||||||
scope | Необходимый Разделенный пробелами список областей, которые определяют ресурсы, к которым ваше приложение может получить доступ от имени пользователя. Эти значения информируют экран согласия, который Google отображает пользователю. Области действия позволяют вашему приложению запрашивать доступ только к тем ресурсам, которые ему нужны, а также позволяют пользователям контролировать объем доступа, который они предоставляют вашему приложению. Таким образом, существует обратная зависимость между количеством запрошенных областей действия и вероятностью получения согласия пользователя. API данных YouTube v3 использует следующие области действия:
Документ «Области действия API OAuth 2.0» содержит полный список областей действия, которые можно использовать для доступа к API Google. Мы рекомендуем, чтобы ваше приложение запрашивало доступ к областям авторизации в контексте, когда это возможно. Запрашивая доступ к данным пользователя в контексте, с помощью инкрементальной авторизации , вы помогаете пользователям легче понять, почему вашему приложению нужен запрашиваемый им доступ. | ||||||||||||||||
access_type | Рекомендовано Указывает, может ли ваше приложение обновлять токены доступа, когда пользователь отсутствует в браузере. Допустимые значения параметров — Установите значение | ||||||||||||||||
state | Рекомендовано Указывает любое строковое значение, которое ваше приложение использует для поддержания состояния между вашим запросом авторизации и ответом сервера авторизации. Сервер возвращает точное значение, которое вы отправляете как пару Этот параметр можно использовать для нескольких целей, например, для направления пользователя на правильный ресурс в вашем приложении, отправки одноразовых кодов и предотвращения подделки межсайтовых запросов. Поскольку ваш | ||||||||||||||||
include_granted_scopes | Необязательный Позволяет приложениям использовать инкрементальную авторизацию для запроса доступа к дополнительным областям в контексте. Если вы установите значение этого параметра равным | ||||||||||||||||
enable_granular_consent | Необязательный По умолчанию Когда Google включит детальные разрешения для приложения, этот параметр больше не будет иметь никакого эффекта. | ||||||||||||||||
login_hint | Необязательный Если ваше приложение знает, какой пользователь пытается пройти аутентификацию, оно может использовать этот параметр для предоставления подсказки серверу аутентификации Google. Сервер использует подсказку для упрощения процесса входа либо путем предварительного заполнения поля электронной почты в форме входа, либо путем выбора соответствующей сессии множественного входа. Задайте в качестве значения параметра адрес электронной почты или | ||||||||||||||||
prompt | Необязательный Разделенный пробелами, чувствительный к регистру список запросов для представления пользователю. Если вы не укажете этот параметр, пользователю будет предложено только в первый раз, когда ваш проект запросит доступ. Для получения дополнительной информации см. Запрос повторного согласия . Возможные значения:
|
Шаг 2: Перенаправление на сервер Google OAuth 2.0
Перенаправить пользователя на сервер OAuth 2.0 Google для инициирования процесса аутентификации и авторизации. Обычно это происходит, когда вашему приложению впервые требуется доступ к данным пользователя. В случае инкрементальной авторизации этот шаг также происходит, когда вашему приложению впервые требуется доступ к дополнительным ресурсам, на доступ к которым у него еще нет разрешения.
PHP
- Создайте URL-адрес для запроса доступа с сервера Google OAuth 2.0:
$auth_url = $client->createAuthUrl();
- Перенаправить пользователя на
$auth_url
:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Питон
В этом примере показано, как перенаправить пользователя на URL-адрес авторизации с помощью фреймворка веб-приложений Flask:
return flask.redirect(authorization_url)
Рубин
- Создайте URL-адрес для запроса доступа с сервера Google OAuth 2.0:
auth_uri = authorizer.get_authorization_url(request: request)
- Перенаправить пользователя на
auth_uri
.
Node.js
- Используйте сгенерированный URL-адрес
authorizationUrl
из шага 1 методаgenerateAuthUrl
для запроса доступа с сервера Google OAuth 2.0. - Перенаправить пользователя на
authorizationUrl
.res.redirect(authorizationUrl);
HTTP/REST
Пример перенаправления на сервер авторизации Google
Пример URL ниже запрашивает автономный доступ ( access_type=offline
) к области, которая разрешает доступ для просмотра учетной записи YouTube пользователя. Он использует инкрементную авторизацию, чтобы гарантировать, что новый токен доступа охватывает все области, к которым пользователь ранее предоставил доступ приложению. URL также задает значения для обязательных параметров redirect_uri
, response_type
и client_id
, а также для параметра state
. URL содержит разрывы строк и пробелы для удобства чтения.
https://accounts.google.com/o/oauth2/v2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
access_type=offline&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
response_type=code&
client_id=client_id
После создания URL-адреса запроса перенаправьте на него пользователя.
Сервер Google OAuth 2.0 аутентифицирует пользователя и получает от него согласие на доступ вашего приложения к запрошенным областям. Ответ отправляется обратно в ваше приложение с использованием указанного вами URL-адреса перенаправления.
Шаг 3: Google запрашивает у пользователя согласие
На этом этапе пользователь решает, предоставить ли вашему приложению запрошенный доступ. На этом этапе Google отображает окно согласия, в котором указано имя вашего приложения и службы API Google, для которых оно запрашивает разрешение на доступ с учетными данными пользователя и сводкой областей доступа, которые должны быть предоставлены. Затем пользователь может дать согласие на предоставление доступа к одной или нескольким областям, запрошенным вашим приложением, или отклонить запрос.
Вашему приложению не нужно ничего делать на этом этапе, поскольку оно ждет ответа от сервера Google OAuth 2.0, указывающего, был ли предоставлен какой-либо доступ. Этот ответ объясняется в следующем шаге.
Ошибки
Запросы к конечной точке авторизации OAuth 2.0 Google могут отображать сообщения об ошибках, с которыми сталкивается пользователь, вместо ожидаемых потоков аутентификации и авторизации. Ниже перечислены распространенные коды ошибок и предлагаемые решения.
admin_policy_enforced
Аккаунт Google не может авторизовать одну или несколько запрошенных областей из-за политик администратора Google Workspace. См. статью справки администратора Google Workspace Управление доступом сторонних и внутренних приложений к данным Google Workspace для получения дополнительной информации о том, как администратор может ограничить доступ ко всем областям или конфиденциальным и ограниченным областям, пока доступ не будет явно предоставлен вашему идентификатору клиента OAuth.
disallowed_useragent
Конечная точка авторизации отображается внутри встроенного пользовательского агента, что запрещено политиками Google OAuth 2.0 .
андроид
Разработчики Android могут столкнуться с этим сообщением об ошибке при открытии запросов авторизации в android.webkit.WebView
. Вместо этого разработчикам следует использовать библиотеки Android, такие как Google Sign-In для Android или AppAuth для Android от OpenID Foundation .
Веб-разработчики могут столкнуться с этой ошибкой, когда приложение Android открывает общую веб-ссылку во встроенном пользовательском агенте, а пользователь переходит на конечную точку авторизации Google OAuth 2.0 с вашего сайта. Разработчики должны разрешить открытие общих ссылок в обработчике ссылок по умолчанию операционной системы, который включает как обработчики ссылок приложений Android , так и приложение браузера по умолчанию. Библиотека Android Custom Tabs также является поддерживаемой опцией.
iOS
Разработчики iOS и macOS могут столкнуться с этой ошибкой при открытии запросов авторизации в WKWebView
. Вместо этого разработчикам следует использовать библиотеки iOS, такие как Google Sign-In для iOS или AppAuth от OpenID Foundation для iOS .
Веб-разработчики могут столкнуться с этой ошибкой, когда приложение iOS или macOS открывает общую веб-ссылку во встроенном пользовательском агенте, а пользователь переходит на конечную точку авторизации Google OAuth 2.0 с вашего сайта. Разработчики должны разрешить открытие общих ссылок в обработчике ссылок по умолчанию операционной системы, который включает как обработчики Universal Links , так и приложение браузера по умолчанию. Библиотека SFSafariViewController
также является поддерживаемой опцией.
org_internal
Идентификатор клиента OAuth в запросе является частью проекта, ограничивающего доступ к аккаунтам Google в определенной организации Google Cloud . Для получения дополнительной информации об этом параметре конфигурации см. раздел Тип пользователя в справочной статье Настройка экрана согласия OAuth.
invalid_client
Неверный секрет клиента OAuth. Проверьте конфигурацию клиента OAuth , включая идентификатор клиента и секрет, использованные для этого запроса.
deleted_client
Клиент OAuth, используемый для выполнения запроса, был удален. Удаление может происходить вручную или автоматически в случае неиспользуемых клиентов . Удаленные клиенты могут быть восстановлены в течение 30 дней с момента удаления. Узнать больше .
invalid_grant
При обновлении токена доступа или использовании инкрементальной авторизации токен мог устареть или стать недействительным. Повторно выполните аутентификацию пользователя и запросите его согласие на получение новых токенов. Если вы продолжаете видеть эту ошибку, убедитесь, что ваше приложение настроено правильно и что вы используете правильные токены и параметры в своем запросе. В противном случае учетная запись пользователя могла быть удалена или отключена.
redirect_uri_mismatch
redirect_uri
переданный в запросе авторизации, не соответствует авторизованному URI перенаправления для идентификатора клиента OAuth. Проверьте авторизованные URI перенаправления в .
Параметр redirect_uri
может ссылаться на поток OAuth out-of-band (OOB), который устарел и больше не поддерживается. Обратитесь к руководству по миграции , чтобы обновить вашу интеграцию.
invalid_request
Что-то не так с вашим запросом. Это может быть вызвано рядом причин:
- Запрос не был правильно отформатирован.
- В запросе отсутствовали обязательные параметры
- Запрос использует метод авторизации, который Google не поддерживает. Убедитесь, что ваша интеграция OAuth использует рекомендуемый метод интеграции
Шаг 4: Обработка ответа сервера OAuth 2.0
Сервер OAuth 2.0 отвечает на запрос доступа вашего приложения, используя URL-адрес, указанный в запросе.
Если пользователь одобряет запрос на доступ, то ответ содержит код авторизации. Если пользователь не одобряет запрос, то ответ содержит сообщение об ошибке. Код авторизации или сообщение об ошибке, возвращаемое веб-серверу, отображается в строке запроса, как показано ниже:
Ошибка в ответе:
https://oauth2.example.com/auth?error=access_denied
Ответ кода авторизации:
https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
Пример ответа сервера OAuth 2.0
Вы можете протестировать этот процесс, нажав на следующий пример URL-адреса, который запрашивает доступ только для чтения для просмотра метаданных файлов на вашем Google Диске и доступ только для чтения для просмотра событий вашего Google Календаря:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly& access_type=offline& include_granted_scopes=true& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=code& client_id=client_id
После завершения потока OAuth 2.0 вы должны быть перенаправлены на http://localhost/oauth2callback
, что, скорее всего, приведет к ошибке 404 NOT FOUND
если только ваша локальная машина не обслуживает файл по этому адресу. Следующий шаг предоставляет более подробную информацию об информации, возвращаемой в URI, когда пользователь перенаправляется обратно в ваше приложение.
Шаг 5: Обмен кода авторизации на токены обновления и доступа
После того как веб-сервер получит код авторизации, он может обменять код авторизации на токен доступа.
PHP
Для обмена кода авторизации на токен доступа используйте метод fetchAccessTokenWithAuthCode
:
$access_token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
Питон
На странице обратного вызова используйте библиотеку google-auth
для проверки ответа сервера авторизации. Затем используйте метод flow.fetch_token
для обмена кода авторизации в этом ответе на токен доступа:
state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/youtube.force-ssl'], state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store the credentials in the session. # ACTION ITEM for developers: # Store user's access and refresh tokens in your data store if # incorporating this code into your real app. credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'granted_scopes': credentials.granted_scopes}
Рубин
На странице обратного вызова используйте библиотеку googleauth
для проверки ответа сервера авторизации. Используйте метод authorizer.handle_auth_callback_deferred
для сохранения кода авторизации и перенаправления обратно на URL, который изначально запросил авторизацию. Это откладывает обмен кодом, временно сохраняя результаты в сеансе пользователя.
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
Для обмена кода авторизации на токен доступа используйте метод getToken
:
const url = require('url'); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); });
HTTP/REST
Чтобы обменять код авторизации на токен доступа, вызовите конечную точку https://oauth2.googleapis.com/token
и задайте следующие параметры:
Поля | |
---|---|
client_id | Идентификатор клиента, полученный от . |
client_secret | Секрет клиента, полученный от . |
code | Код авторизации, возвращенный из первоначального запроса. |
grant_type | Как определено в спецификации OAuth 2.0 , значение этого поля должно быть установлено на authorization_code . |
redirect_uri | Один из URI перенаправления, перечисленных для вашего проекта в для указанного client_id . |
В следующем фрагменте показан пример запроса:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your_client_id& client_secret=your_client_secret& redirect_uri=https%3A//oauth2.example.com/code& grant_type=authorization_code
Google отвечает на этот запрос, возвращая объект JSON, содержащий краткосрочный токен доступа и токен обновления. Обратите внимание, что токен обновления возвращается только в том случае, если ваше приложение установило параметр access_type
на offline
в первоначальном запросе к серверу авторизации Google .
Ответ содержит следующие поля:
Поля | |
---|---|
access_token | Токен, который ваше приложение отправляет для авторизации запроса API Google. |
expires_in | Оставшееся время жизни токена доступа в секундах. |
refresh_token | Токен, который можно использовать для получения нового токена доступа. Токены обновления действительны до тех пор, пока пользователь не отменит доступ или не истечет срок действия токена обновления. Опять же, это поле присутствует в этом ответе только в том случае, если вы установили параметр access_type на offline в первоначальном запросе к серверу авторизации Google. |
refresh_token_expires_in | Оставшееся время жизни токена обновления в секундах. Это значение устанавливается только тогда, когда пользователь предоставляет доступ на основе времени . |
scope | Области доступа, предоставляемые access_token , выраженные в виде списка разделенных пробелами строк с учетом регистра. |
token_type | Тип возвращаемого токена. В настоящее время значение этого поля всегда установлено на Bearer . |
В следующем фрагменте показан пример ответа:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/youtube.force-ssl", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
Ошибки
При обмене кода авторизации на токен доступа вы можете столкнуться со следующей ошибкой вместо ожидаемого ответа. Ниже перечислены распространенные коды ошибок и предлагаемые решения.
invalid_grant
Предоставленный код авторизации недействителен или имеет неправильный формат. Запросите новый код, перезапустив процесс OAuth, чтобы снова запросить у пользователя согласие.
Шаг 6: Проверьте, какие области действия предоставили пользователи
При запросе нескольких разрешений (областей действия) пользователи могут не предоставить вашему приложению доступ ко всем из них. Ваше приложение должно проверять, какие области действия были фактически предоставлены, и корректно обрабатывать ситуации, когда некоторые разрешения отклоняются, обычно отключая функции, которые полагаются на эти отклоненные области действия.
Однако есть исключения. Приложения Google Workspace Enterprise с делегированием полномочий на весь домен или приложения, помеченные как Trusted , обходят экран согласия на детализированные разрешения. Для этих приложений пользователи не увидят экран согласия на детализированные разрешения. Вместо этого ваше приложение либо получит все запрошенные области, либо ни одной.
Более подробную информацию см. в разделе Как работать с детализированными разрешениями .
PHP
Чтобы проверить, какие области действия предоставил пользователь, используйте метод getGrantedScope()
:
// Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope();
Питон
Возвращенный объект credentials
имеет свойство granted_scopes
, которое представляет собой список областей, предоставленных пользователем вашему приложению.
credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'granted_scopes': credentials.granted_scopes}
Рубин
При одновременном запросе нескольких областей проверьте, какие области были предоставлены через свойство scope
объекта credentials
.
# User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::YoutubeV3::AUTH_YOUTUBE_FORCE_SSL) # User authorized permission to see, edit, and permanently delete the # YouTube videos, ratings, comments and captions. # Calling the APIs, etc else # User didn't authorize the permission. # Update UX and application accordingly end
Node.js
При одновременном запросе нескольких областей проверьте, какие области были предоставлены через свойство scope
объекта tokens
.
// User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/youtube.force-ssl')) { // User authorized permission to see, edit, and permanently delete the // YouTube videos, ratings, comments and captions. // Calling the APIs, etc. } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly }
HTTP/REST
Чтобы проверить, предоставил ли пользователь вашему приложению доступ к определенной области, проверьте поле scope
в ответе токена доступа. Области доступа, предоставленные access_token, выражены в виде списка разделенных пробелами, чувствительных к регистру строк.
Например, следующий пример ответа токена доступа указывает на то, что пользователь предоставил вашему приложению разрешение просматривать, редактировать и навсегда удалять видео, оценки, комментарии и субтитры пользователя на YouTube:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/youtube.force-ssl", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
Вызов API Google
PHP
Используйте токен доступа для вызова API Google, выполнив следующие шаги:
- Если вам необходимо применить токен доступа к новому объекту
Google\Client
— например, если вы сохранили токен доступа в сеансе пользователя — используйте методsetAccessToken
:$client->setAccessToken($access_token);
- Создайте объект службы для API, который вы хотите вызвать. Вы создаете объект службы, предоставляя авторизованный объект
Google\Client
конструктору для API, который вы хотите вызвать. Например, чтобы вызвать API данных YouTube:$youtube = new Google_Service_YouTube($client);
- Выполняйте запросы к API-сервису, используя интерфейс, предоставляемый объектом сервиса . Например, для получения данных о канале YouTube авторизованного пользователя:
$channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));
Питон
После получения токена доступа ваше приложение может использовать этот токен для авторизации запросов API от имени данной учетной записи пользователя или учетной записи службы. Используйте учетные данные авторизации, специфичные для пользователя, для создания объекта службы для API, который вы хотите вызвать, а затем используйте этот объект для выполнения авторизованных запросов API.
- Создайте объект службы для API, который вы хотите вызвать. Вы создаете объект службы, вызывая метод
build
библиотекиgoogleapiclient.discovery
с именем и версией API и учетными данными пользователя: Например, чтобы вызвать версию 3 API данных YouTube:from googleapiclient.discovery import build youtube = build('youtube', 'v3', credentials=credentials)
- Выполняйте запросы к API-сервису, используя интерфейс, предоставляемый объектом сервиса . Например, для получения данных о канале YouTube авторизованного пользователя:
channel = youtube.channels().list(mine=True, part='snippet').execute()
Рубин
После получения токена доступа ваше приложение может использовать этот токен для выполнения запросов API от имени данной учетной записи пользователя или учетной записи службы. Используйте учетные данные авторизации, специфичные для пользователя, для создания объекта службы для API, который вы хотите вызвать, а затем используйте этот объект для выполнения авторизованных запросов API.
- Создайте объект службы для API, который вы хотите вызвать. Например, чтобы вызвать версию 3 API данных YouTube:
youtube = Google::Apis::YoutubeV3::YouTubeService.new
- Установите учетные данные на сервисе:
youtube.authorization = credentials
- Выполняйте запросы к API-сервису, используя интерфейс, предоставляемый объектом сервиса . Например, для получения данных о канале YouTube авторизованного пользователя:
channel = youtube.list_channels(part, :mine => mine)
В качестве альтернативы авторизация может быть предоставлена для каждого метода отдельно, путем указания параметра options
для метода:
channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })
Node.js
После получения токена доступа и установки его в объект OAuth2
используйте объект для вызова API Google. Ваше приложение может использовать этот токен для авторизации запросов API от имени заданной учетной записи пользователя или учетной записи службы. Создайте объект службы для API, который вы хотите вызвать. Например, следующий код использует API Google Drive для перечисления имен файлов на Диске пользователя.
const { google } = require('googleapis'); // Example of using YouTube API to list channels. var service = google.youtube('v3'); service.channels.list({ auth: oauth2Client, part: 'snippet,contentDetails,statistics', forUsername: 'GoogleDevelopers' }, function (err, response) { if (err) { console.log('The API returned an error: ' + err); return; } var channels = response.data.items; if (channels.length == 0) { console.log('No channel found.'); } else { console.log('This channel\'s ID is %s. Its title is \'%s\', and ' + 'it has %s views.', channels[0].id, channels[0].snippet.title, channels[0].statistics.viewCount); } });
HTTP/REST
После того, как ваше приложение получит токен доступа, вы сможете использовать его для вызовов API Google от имени данной учетной записи пользователя, если область(ы) доступа, требуемые API, были предоставлены. Для этого включите токен доступа в запрос к API, включив либо параметр запроса access_token
, либо значение заголовка HTTP Authorization
Bearer
. Когда это возможно, предпочтительнее использовать заголовок HTTP, поскольку строки запросов, как правило, видны в журналах сервера. В большинстве случаев вы можете использовать клиентскую библиотеку для настройки вызовов API Google (например, при вызове API данных YouTube ).
Обратите внимание, что API данных YouTube поддерживает учетные записи служб только для владельцев контента YouTube, которые владеют и управляют несколькими каналами YouTube, например, звукозаписывающими компаниями и киностудиями.
Вы можете опробовать все API Google и ознакомиться с их возможностями на OAuth 2.0 Playground .
Примеры HTTP GET
Вызов конечной точки youtube.channels
(API данных YouTube) с использованием HTTP-заголовка Authorization: Bearer
может выглядеть следующим образом. Обратите внимание, что вам необходимо указать собственный токен доступа:
GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
Вот вызов того же API для аутентифицированного пользователя с использованием параметра строки запроса access_token
:
GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
примеры curl
Вы можете протестировать эти команды с помощью приложения командной строки curl
. Вот пример, который использует опцию заголовка HTTP (предпочтительно):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true
Или, в качестве альтернативы, параметр строки запроса:
curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
Полный пример
В следующем примере выводится объект в формате JSON, отображающий информацию о канале пользователя на YouTube после того, как пользователь пройдет аутентификацию и авторизует приложение для управления учетной записью пользователя на YouTube.
PHP
Чтобы запустить этот пример:
- В API Console, добавьте URL локальной машины в список URL-адресов перенаправления. Например, добавьте
http://localhost:8080
. - Создайте новый каталог и перейдите в него. Например:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- Установите клиентскую библиотеку Google API для PHP с помощью Composer :
composer require google/apiclient:^2.15.0
- Создайте файлы
index.php
иoauth2callback.php
со следующим содержимым. - Запустите пример с помощью встроенного тестового веб-сервера PHP:
php -S localhost:8080 ~/php-oauth2-example
индекс.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfig('client_secret.json'); // User granted permission as an access token is in the session. if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); $youtube = new Google_Service_YouTube($client); $channel = $youtube->channels->listChannels('snippet', array('mine' => $mine)); echo json_encode($channel); } else { // Redirect users to outh2call.php which redirects users to Google OAuth 2.0 $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } ?>
oauth2callback.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfigFile('client_secret.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF']); // Required, to set the scope value, call the addScope function. $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); // Enable incremental authorization. Recommended as a best practice. $client->setIncludeGrantedScopes(true); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType("offline"); // Generate a URL for authorization as it doesn't contain code and error if (!isset($_GET['code']) && !isset($_GET['error'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; // Generate a url that asks permissions. $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } // User authorized the request and authorization code is returned to exchange access and // refresh tokens. if (isset($_GET['code'])) { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } // Get access and refresh tokens (if access_type is offline) $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); /** Save access and refresh token to the session variables. * ACTION ITEM: In a production app, you likely want to save the * refresh token in a secure persistent storage instead. */ $_SESSION['access_token'] = $token; $_SESSION['refresh_token'] = $client->getRefreshToken(); $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } // An error response e.g. error=access_denied if (isset($_GET['error'])) { echo "Error: ". $_GET['error']; } ?>
Питон
В этом примере используется фреймворк Flask . Он запускает веб-приложение по http://localhost:8080
которое позволяет вам протестировать поток OAuth 2.0. Если вы перейдете по этому URL, вы должны увидеть пять ссылок:
- Тест запроса API: эта ссылка указывает на страницу, которая пытается выполнить пример запроса API. При необходимости она запускает поток авторизации. В случае успеха страница отображает ответ API.
- Протестируйте поток аутентификации напрямую: эта ссылка указывает на страницу, которая пытается отправить пользователя через поток авторизации . Приложение запрашивает разрешение на отправку авторизованных запросов API от имени пользователя.
- Отозвать текущие учетные данные: эта ссылка ведет на страницу, которая отменяет разрешения, которые пользователь уже предоставил приложению.
- Очистить учетные данные сеанса Flask: эта ссылка очищает учетные данные авторизации, которые хранятся в сеансе Flask. Это позволяет вам увидеть, что произойдет, если пользователь, который уже предоставил разрешение вашему приложению, попытается выполнить запрос API в новом сеансе. Это также позволяет вам увидеть ответ API, который получит ваше приложение, если пользователь отменил разрешения, предоставленные вашему приложению, а ваше приложение все еще пытается авторизовать запрос с отозванным токеном доступа.
# -*- coding: utf-8 -*- import os import flask import requests import google.oauth2.credentials import google_auth_oauthlib.flow import googleapiclient.discovery # This variable specifies the name of a file that contains the OAuth 2.0 # information for this application, including its client_id and client_secret. CLIENT_SECRETS_FILE = "client_secret.json" # The OAuth 2.0 access scope allows for access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl'] API_SERVICE_NAME = 'youtube' API_VERSION = 'v3' app = flask.Flask(__name__) # Note: A secret key is included in the sample so that it works. # If you use this code in your application, replace this with a truly secret # key. See https://flask.palletsprojects.com/quickstart/#sessions. app.secret_key = 'REPLACE ME - this value is here as a placeholder.' @app.route('/') def index(): return print_index_table() @app.route('/test') def test_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') # Load credentials from the session. credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) youtube = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) channel = youtube.channels().list(mine=True, part='snippet').execute() # Save credentials back to session in case access token was refreshed. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**channel) @app.route('/authorize') def authorize(): # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES) # The URI created here must exactly match one of the authorized redirect URIs # for the OAuth 2.0 client, which you configured in the API Console. If this # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch' # error. flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true') # Store the state so the callback can verify the auth server response. flask.session['state'] = state return flask.redirect(authorization_url) @app.route('/oauth2callback') def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. credentials = flow.credentials flask.session['credentials'] = credentials_to_dict(credentials) return flask.redirect(flask.url_for('test_api_request')) @app.route('/revoke') def revoke(): if 'credentials' not in flask.session: return ('You need to <a href="/authorize">authorize</a> before ' + 'testing the code to revoke credentials.') credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) revoke = requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'}) status_code = getattr(revoke, 'status_code') if status_code == 200: return('Credentials successfully revoked.' + print_index_table()) else: return('An error occurred.' + print_index_table()) @app.route('/clear') def clear_credentials(): if 'credentials' in flask.session: del flask.session['credentials'] return ('Credentials have been cleared.<br><br>' + print_index_table()) def credentials_to_dict(credentials): return {'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'granted_scopes': credentials.granted_scopes} def print_index_table(): return ('<table>' + '<tr><td><a href="/test">Test an API request</a></td>' + '<td>Submit an API request and see a formatted JSON response. ' + ' Go through the authorization flow if there are no stored ' + ' credentials for the user.</td></tr>' + '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' + '<td>Go directly to the authorization flow. If there are stored ' + ' credentials, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/revoke">Revoke current credentials</a></td>' + '<td>Revoke the access token associated with the current user ' + ' session. After revoking credentials, if you go to the test ' + ' page, you should see an <code>invalid_grant</code> error.' + '</td></tr>' + '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' + '<td>Clear the access token currently stored in the user session. ' + ' After clearing the token, if you <a href="/test">test the ' + ' API request</a> again, you should go back to the auth flow.' + '</td></tr></table>') if __name__ == '__main__': # When running locally, disable OAuthlib's HTTPs verification. # ACTION ITEM for developers: # When running in production *do not* leave this option enabled. os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # This disables the requested scopes and granted scopes check. # If users only grant partial request, the warning would not be thrown. os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1' # Specify a hostname and port that are set as a valid redirect URI # for your API project in the Google API Console. app.run('localhost', 8080, debug=True)
Рубин
В этом примере используется фреймворк Sinatra .
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/youtube_v3' require 'sinatra' configure do enable :sessions # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for retrieving data about the user's YouTube channel. scope = 'Google::Apis::YoutubeV3::AUTH_YOUTUBE_FORCE_SSL' # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. set :callback_uri, '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, callback_uri: settings.callback_uri) end get '/' do # NOTE: Assumes the user is already authenticated to the app user_id = request.session['user_id'] # Fetch stored credentials for the user from the given request session. # nil if none present credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? # Generate a url that asks the user to authorize requested scope(s). # Then, redirect user to the url. redirect settings.authorizer.get_authorization_url(request: request) end # User authorized read-only YouTube Data API permission. # Example of using YouTube Data API to list user's YouTube channel youtube = Google::Apis::YoutubeV3::YouTubeService.new channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client }) "<pre>#{JSON.pretty_generate(channel.to_h)}</pre>" end # Receive the callback from Google's OAuth 2.0 server. get '/oauth2callback' do # Handle the result of the oauth callback. Defers the exchange of the code by # temporarily stashing the results in the user's session. target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
Чтобы запустить этот пример:
- В API Console, добавьте URL локальной машины в список URL перенаправления. Например, добавьте
http://localhost
. - Убедитесь, что у вас установлена поддержка LTS, активная LTS или текущая версия Node.js.
- Создайте новый каталог и перейдите в него. Например:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
- Установите клиентскую библиотеку Google API для Node.js с помощью npm :
npm install googleapis
- Создайте файлы
main.js
со следующим содержимым. - Запустите пример:
node .\main.js
main.js
const http = require('http'); const https = require('https'); const url = require('url'); const { google } = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI. * To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for YouTube API const scopes = [ 'https://www.googleapis.com/auth/youtube.force-ssl' ]; /* Global variable that stores user credential in this code example. * ACTION ITEM for developers: * Store user's refresh token in your data store if * incorporating this code into your real app. * For more information on handling refresh tokens, * see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens */ let userCredential = null; async function main() { const app = express(); app.use(session({ secret: 'your_secure_secret_key', // Replace with a strong secret resave: false, saveUninitialized: false, })); // Example on redirecting user to Google's OAuth 2.0 server. app.get('/', async (req, res) => { // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity and Google Calendar scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state }); res.redirect(authorizationUrl); }); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { // Handle the OAuth 2.0 server response let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); /** Save credential to the global variable in case access token was refreshed. * ACTION ITEM: In a production app, you likely want to save the refresh token * in a secure persistent database instead. */ userCredential = tokens; // Example of using YouTube API to list channels. var service = google.youtube('v3'); service.channels.list({ auth: oauth2Client, part: 'snippet,contentDetails,statistics', forUsername: 'GoogleDevelopers' }, function (err, response) { if (err) { console.log('The API returned an error: ' + err); return; } var channels = response.data.items; if (channels.length == 0) { console.log('No channel found.'); } else { console.log('This channel\'s ID is %s. Its title is \'%s\', and ' + 'it has %s views.', channels[0].id, channels[0].snippet.title, channels[0].statistics.viewCount); } }); } }); // Example on revoking a token app.get('/revoke', async (req, res) => { // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end(); }); const server = http.createServer(app); server.listen(8080); } main().catch(console.error);
HTTP/REST
В этом примере Python используется фреймворк Flask и библиотека Requests для демонстрации веб-потока OAuth 2.0. Для этого потока мы рекомендуем использовать клиентскую библиотеку Google API для Python. (Пример на вкладке Python использует клиентскую библиотеку.)
import json import flask import requests app = flask.Flask(__name__) # To get these credentials (CLIENT_ID CLIENT_SECRET) and for your application, visit # https://console.cloud.google.com/apis/credentials. CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app # Access scopes for YouTube API SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl' # Indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. REDIRECT_URI = 'http://example.com/oauth2callback' @app.route('/') def index(): if 'credentials' not in flask.session: return flask.redirect(flask.url_for('oauth2callback')) credentials = json.loads(flask.session['credentials']) if credentials['expires_in'] <= 0: return flask.redirect(flask.url_for('oauth2callback')) else: headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://www.googleapis.com/youtube/v3/channels/list' r = requests.get(req_uri, headers=headers) return r.text @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state # Generate a url that asks permissions for the Drive activity # and Google Calendar scope. Then, redirect user to the url. auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code' '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI, SCOPE, state) return flask.redirect(auth_uri) else: if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']: return 'State mismatch. Possible CSRF attack.', 400 auth_code = flask.request.args.get('code') data = {'code': auth_code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code'} # Exchange authorization code for access and refresh tokens (if access_type is offline) r = requests.post('https://oauth2.googleapis.com/token', data=data) flask.session['credentials'] = r.text return flask.redirect(flask.url_for('index')) if __name__ == '__main__': import uuid app.secret_key = str(uuid.uuid4()) app.debug = False app.run()
Правила проверки URI перенаправления
Google применяет следующие правила проверки для перенаправления URI, чтобы помочь разработчикам поддерживать безопасность своих приложений. Ваши перенаправления URI должны соответствовать этим правилам. См. раздел 3 RFC 3986 для определения домена, хоста, пути, запроса, схемы и информации о пользователе, упомянутых ниже.
Правила проверки | |
---|---|
Схема | URI перенаправления должны использовать схему HTTPS, а не обычный HTTP. Локальные URI (включая URI IP-адреса локального хоста) освобождены от этого правила. |
Хозяин | Хосты не могут быть сырыми IP-адресами. IP-адреса локальных хостов исключены из этого правила. |
Домен | “googleusercontent.com” .goo.gl ), если только приложение не владеет доменом. Кроме того, если приложение, владеющее доменом сокращения, выбирает перенаправление на этот домен, этот URI перенаправления должен либо содержать “/google-callback/” в своем пути, либо заканчиваться на “/google-callback” . |
Информация о пользователе | URI перенаправления не могут содержать подкомпонент userinfo. |
Путь | URI перенаправления не могут содержать обход пути (также называемый возвратом к каталогу), который представлен символами |
Запрос | URI перенаправления не могут содержать открытые перенаправления . |
Фрагмент | URI перенаправления не могут содержать компонент фрагмента. |
Персонажи | URI перенаправления не могут содержать определенные символы, включая:
|
Инкрементная авторизация
В протоколе OAuth 2.0 ваше приложение запрашивает авторизацию для доступа к ресурсам, которые идентифицируются по областям действия. Считается лучшей практикой для пользователя запрашивать авторизацию для ресурсов в то время, когда они вам нужны. Чтобы реализовать эту практику, сервер авторизации Google поддерживает инкрементальную авторизацию. Эта функция позволяет вам запрашивать области действия по мере необходимости и, если пользователь предоставляет разрешение на новую область действия, возвращает код авторизации, который можно обменять на токен, содержащий все области действия, которые пользователь предоставил проекту.
Например, предположим, что приложение помогает пользователям находить интересные местные события. Приложение позволяет пользователям просматривать видео о событиях, оценивать видео и добавлять видео в плейлисты. Пользователи также могут использовать приложение для добавления событий в свои календари Google.
В этом случае при входе в систему приложению может не потребоваться или не потребоваться доступ к каким-либо областям. Однако, если пользователь попытается оценить видео, добавить видео в плейлист или выполнить другое действие на YouTube, приложение может запросить доступ к области https://www.googleapis.com/auth/youtube.force-ssl
. Аналогичным образом приложение может запросить доступ к области https://www.googleapis.com/auth/calendar
, если пользователь попытается добавить событие в календаре.
Чтобы реализовать инкрементальную авторизацию, вы завершаете обычный поток запроса токена доступа, но убедитесь, что запрос авторизации включает ранее предоставленные области. Такой подход позволяет вашему приложению избежать необходимости управлять несколькими токенами доступа.
К токену доступа, полученному в результате инкрементной авторизации, применяются следующие правила:
- Токен можно использовать для доступа к ресурсам, соответствующим любой из областей, включенных в новую комбинированную авторизацию.
- При использовании токена обновления для комбинированной авторизации с целью получения токена доступа токен доступа представляет собой комбинированную авторизацию и может использоваться для любого из значений
scope
, включенных в ответ. - Объединенная авторизация включает все области, которые пользователь предоставил проекту API, даже если гранты были запрошены у разных клиентов. Например, если пользователь предоставил доступ к одной области с помощью настольного клиента приложения, а затем предоставил другую область тому же приложению через мобильный клиент, объединенная авторизация будет включать обе области.
- Если вы отзовете токен, представляющий комбинированную авторизацию, доступ ко всем областям этой авторизации от имени соответствующего пользователя будет отозван одновременно.
Примеры кода, специфичные для языка, в Шаге 1: Установка параметров авторизации и пример URL-адреса перенаправления HTTP/REST в Шаге 2: Перенаправление на сервер Google OAuth 2.0 используют инкрементальную авторизацию. Примеры кода ниже также показывают код, который необходимо добавить для использования инкрементальной авторизации.
PHP
$client->setIncludeGrantedScopes(true);
Питон
В Python установите аргумент ключевого слова include_granted_scopes
в true
, чтобы гарантировать, что запрос на авторизацию включает ранее предоставленные области. Вполне возможно, что include_granted_scopes
не будет единственным аргументом ключевого слова, который вы установите, как показано в примере ниже.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Рубин
auth_client.update!( :additional_parameters => {"include_granted_scopes" => "true"} )
Node.js
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
HTTP/REST
В этом примере вызывающее приложение запрашивает доступ для извлечения данных YouTube Analytics пользователя в дополнение к любому другому доступу, который пользователь уже предоставил приложению.
GET https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly& access_type=offline& state=security_token%3D138rk%3Btarget_url%3Dhttp...index& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=code& client_id=client_id& include_granted_scopes=true
Refreshing an access token (offline access)
Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.
- If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
- If you are not using a client library, you need to set the
access_type
HTTP query parameter tooffline
when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.
Requesting offline access is a requirement for any application that needs to access a Google
API when the user is not present. For example, an app that performs backup services or
executes actions at predetermined times needs to be able to refresh its access token when the
user is not present. The default style of access is called online
.
Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.
PHP
If your application needs offline access to a Google API, set the API client's access type to
offline
:
$client->setAccessType("offline");
После того, как пользователь предоставит офлайн-доступ к запрошенным областям, вы можете продолжать использовать API-клиент для доступа к API Google от имени пользователя, когда пользователь находится в офлайн-режиме. Клиентский объект обновит токен доступа по мере необходимости.
Питон
В Python установите ключевой аргумент access_type
в offline
, чтобы гарантировать, что вы сможете обновить токен доступа без необходимости повторно запрашивать у пользователя разрешение. Вполне возможно, что access_type
не будет единственным ключевым аргументом, который вы установите, как показано в примере ниже.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
После того, как пользователь предоставит офлайн-доступ к запрошенным областям, вы можете продолжать использовать API-клиент для доступа к API Google от имени пользователя, когда пользователь находится в офлайн-режиме. Клиентский объект обновит токен доступа по мере необходимости.
Рубин
Если вашему приложению требуется автономный доступ к API Google, установите тип доступа клиента API на offline
:
auth_client.update!( :additional_parameters => {"access_type" => "offline"} )
После того, как пользователь предоставит офлайн-доступ к запрошенным областям, вы можете продолжать использовать API-клиент для доступа к API Google от имени пользователя, когда пользователь находится в офлайн-режиме. Клиентский объект обновит токен доступа по мере необходимости.
Node.js
Если вашему приложению требуется автономный доступ к API Google, установите тип доступа клиента API на offline
:
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
После того, как пользователь предоставит офлайн-доступ к запрошенным областям, вы можете продолжать использовать API-клиент для доступа к API Google от имени пользователя, когда пользователь находится в офлайн-режиме. Клиентский объект обновит токен доступа по мере необходимости.
Срок действия токенов доступа истекает. Эта библиотека автоматически использует токен обновления для получения нового токена доступа, если срок его действия истекает. Простой способ убедиться, что вы всегда сохраняете самые последние токены, — использовать событие токенов:
oauth2Client.on('tokens', (tokens) => { if (tokens.refresh_token) { // store the refresh_token in your secure persistent database console.log(tokens.refresh_token); } console.log(tokens.access_token); });
Это событие токенов происходит только при первой авторизации, и вам необходимо установить access_type
на offline
при вызове метода generateAuthUrl
для получения токена обновления. Если вы уже предоставили своему приложению требуемые разрешения, не установив соответствующие ограничения для получения токена обновления, вам нужно будет повторно авторизовать приложение, чтобы получить свежий токен обновления.
Чтобы установить refresh_token
на более позднее время, можно использовать метод setCredentials
:
oauth2Client.setCredentials({ refresh_token: `STORED_REFRESH_TOKEN` });
Как только у клиента появится токен обновления, токены доступа будут автоматически получены и обновлены при следующем вызове API.
HTTP/REST
Чтобы обновить токен доступа, ваше приложение отправляет HTTPS POST
запрос на сервер авторизации Google ( https://oauth2.googleapis.com/token
), включающий следующие параметры:
Поля | |
---|---|
client_id | Идентификатор клиента, полученный от API Console. |
client_secret | Секрет клиента, полученный от API Console. |
grant_type | Как определено в спецификации OAuth 2.0 , значение этого поля должно быть установлено на refresh_token . |
refresh_token | Токен обновления, возвращенный в результате обмена кодами авторизации. |
В следующем фрагменте показан пример запроса:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded client_id=your_client_id& client_secret=your_client_secret& refresh_token=refresh_token& grant_type=refresh_token
Пока пользователь не отменил доступ, предоставленный приложению, сервер токенов возвращает объект JSON, содержащий новый токен доступа. Следующий фрагмент показывает пример ответа:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "scope": "https://www.googleapis.com/auth/drive.metadata.readonly", "token_type": "Bearer" }
Обратите внимание, что существуют ограничения на количество выдаваемых токенов обновления: одно ограничение на комбинацию клиент/пользователь и еще одно ограничение на пользователя по всем клиентам. Вам следует сохранять токены обновления в долгосрочном хранилище и продолжать использовать их, пока они остаются действительными. Если ваше приложение запрашивает слишком много токенов обновления, оно может столкнуться с этими ограничениями, и в этом случае старые токены обновления перестанут работать.
Отзыв токена
В некоторых случаях пользователь может захотеть отозвать доступ, предоставленный приложению. Пользователь может отозвать доступ, посетив Настройки учетной записи . Дополнительную информацию см. в разделе Удалить доступ к сайту или приложению в документе поддержки Сторонние сайты и приложения с доступом к вашей учетной записи .
Приложение также может программно отозвать предоставленный ему доступ. Программный отзыв важен в случаях, когда пользователь отписывается, удаляет приложение или ресурсы API, необходимые приложению, существенно изменились. Другими словами, часть процесса удаления может включать запрос API, чтобы гарантировать, что разрешения, ранее предоставленные приложению, будут удалены.
PHP
Чтобы программно отозвать токен, вызовите revokeToken()
:
$client->revokeToken();
Питон
Чтобы программно отозвать токен, отправьте запрос на https://oauth2.googleapis.com/revoke
, включив токен в качестве параметра и установив заголовок Content-Type
:
requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'})
Рубин
Чтобы программно отозвать токен, отправьте HTTP-запрос к конечной точке oauth2.revoke
:
uri = URI('https://oauth2.googleapis.com/revoke') response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
Токен может быть токеном доступа или токеном обновления. Если токен является токеном доступа и у него есть соответствующий токен обновления, токен обновления также будет отозван.
Если отзыв успешно обработан, то код статуса ответа — 200
В случае возникновения ошибок возвращается код статуса 400
вместе с кодом ошибки.
Node.js
Чтобы программно отозвать токен, отправьте HTTPS-запрос POST к конечной точке /revoke
:
const https = require('https'); // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end();
Параметр токена может быть токеном доступа или токеном обновления. Если токен является токеном доступа и у него есть соответствующий токен обновления, токен обновления также будет отозван.
Если отзыв успешно обработан, то код статуса ответа — 200
В случае возникновения ошибок возвращается код статуса 400
вместе с кодом ошибки.
HTTP/REST
Чтобы программно отозвать токен, ваше приложение отправляет запрос на https://oauth2.googleapis.com/revoke
и включает токен в качестве параметра:
curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \ https://oauth2.googleapis.com/revoke?token={token}
Токен может быть токеном доступа или токеном обновления. Если токен является токеном доступа и у него есть соответствующий токен обновления, токен обновления также будет отозван.
Если отзыв успешно обработан, то код статуса HTTP ответа равен 200
В случае возникновения ошибок возвращается код статуса HTTP 400
вместе с кодом ошибки.
Доступ по времени
Доступ на основе времени позволяет пользователю предоставить вашему приложению доступ к своим данным на ограниченный период времени для выполнения действия. Доступ на основе времени доступен в некоторых продуктах Google во время потока согласия, предоставляя пользователям возможность предоставить доступ на ограниченный период времени. Примером является API переносимости данных , который позволяет выполнять однократную передачу данных.
Когда пользователь предоставляет вашему приложению доступ на основе времени, токен обновления истекает по истечении указанного периода. Обратите внимание, что токены обновления могут быть аннулированы раньше при определенных обстоятельствах; см. эти случаи для получения подробной информации. Поле refresh_token_expires_in
возвращаемое в ответе обмена кодом авторизации, представляет собой время, оставшееся до истечения срока действия токена обновления в таких случаях.
Реализация защиты перекрестных счетов
Дополнительным шагом, который вам следует предпринять для защиты учетных записей пользователей, является внедрение Cross-Account Protection с помощью службы Cross-Account Protection от Google. Эта служба позволяет вам подписываться на уведомления о событиях безопасности, которые предоставляют вашему приложению информацию о важных изменениях в учетной записи пользователя. Затем вы можете использовать эту информацию для выполнения действий в зависимости от того, как вы решите реагировать на события.
Вот некоторые примеры типов событий, отправляемых в ваше приложение службой защиты перекрестных аккаунтов Google:
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
-
https://schemas.openid.net/secevent/oauth/event-type/token-revoked
-
https://schemas.openid.net/secevent/risc/event-type/account-disabled
Дополнительную информацию о реализации защиты перекрестных учетных записей и полный список доступных событий см. на странице Защита учетных записей пользователей с помощью защиты перекрестных учетных записей.